package com.codebase.alicloud.oss;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @describe: 文件上传下载到OSS的工具类
 * @author:houkai
 * @Date: 2018/3/7 14:54
 * @version 1.0
 */
public class OSSUtil {

    private static final String SLANT = "/";
    private static final String DOT = ".";
    public static final String ETag = "ETag";
    public static final String OSSFilePathName = "OSSFilePathName";
    /**
     * 上传文件到OSS服务器
     *
     * @param client OSSClient
     * @param file 原文件
     * @param bucketName bucket名称
     * @param ossFilePath oss文件路径
     * @param ossFileName oss文件名（文件名未包含拓展名）
     * @return result 出参Map中包含两个参数：
     *                ETag 返回的MD5Key
     *                OSSFilePathName OSS文件路径
     */
    public static Map<String, String> uploadFile (OSSClient client, File file, String bucketName, String ossFilePath, String ossFileName) {
        Map<String, String> result = new HashMap<String, String>(2);
        try {
            InputStream in = new FileInputStream(file);
            if (file != null && file.exists()) {
                String oriFileName = file.getName();
                //截取拓展名;
                String fileExtension = oriFileName.substring(oriFileName.lastIndexOf(DOT));
                StringBuffer ossPath = new StringBuffer();
                ossPath.append(ossFilePath);
                if (!ossFilePath.endsWith(SLANT)) {
                    ossPath.append(SLANT);
                }
                //拼接OSS文件路径
                ossPath.append(ossFileName);
                Long fileSize = file.length();
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentLength(in.available());
                metadata.setCacheControl("no-cache");
                metadata.setContentEncoding("utf-8");
                metadata.setHeader("Pragma", "no-cache");
                metadata.setContentType(FileExtensionEnum.getContentTypeByExtension(fileExtension));
                metadata.setContentDisposition("filename/filesize=" + ossFileName + "/" + fileSize + "Byte.");
                PutObjectResult putResult = client.putObject(bucketName, ossPath.toString(), in, metadata);
                //MD5值
                result.put(ETag, putResult.getETag());
                //oss 文件路径 + 文件名 /test/test.png
                result.put(OSSFilePathName, ossPath.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件从OSS下载出现异常");
        }
        return result;
    }

    /**
     * 新建Bucket
     * @param client
     * @param bucketName
     * @return
     */
    public static final boolean addBucket(OSSClient client, String bucketName) {
        Bucket bucket = client.createBucket(bucketName);
        return bucketName.equals(bucket.getName());
    }

    /**
     *  下载文件
     * @param client  OSSClient对象
     * @param bucketName    Bucket名
     * @param ossFilePath  上传到OSS起的全路径名
     * @param filename     文件下载到本地保存的路径
     * @throws OSSException
     * @throws ClientException
     */
    public static void downloadFile(OSSClient client, String bucketName, String ossFilePath, String filename) {
        try{
            client.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(filename));
        } catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("文件从OSS下载出现异常");
        }
    }

    /**
     * 删除一个Bucket和其中的Objects
     *
     * @param client  OSSClient对象
     * @param bucketName  Bucket名
     * @throws OSSException
     * @throws ClientException
     */
    public static void deleteBucket(OSSClient client, String bucketName)throws OSSException, ClientException{
        ObjectListing objectListing = client.listObjects(bucketName);
        List<OSSObjectSummary> listDeletes = objectListing.getObjectSummaries();
        for(int i = 0; i < listDeletes.size(); i++){
            String objectName = listDeletes.get(i).getKey();
            System.out.println("objectName = " + objectName);
            //如果不为空，先删除bucket下的文件
            client.deleteObject(bucketName, objectName);
        }
        client.deleteBucket(bucketName);
    }

    /**
     * 把Bucket设置成所有人可读
     *
     * @param client  OSSClient对象
     * @param bucketName  Bucket名
     * @throws OSSException
     * @throws ClientException
     */
    public static void setBucketPublicReadable(OSSClient client, String bucketName)throws OSSException, ClientException{
        //创建bucket
        client.createBucket(bucketName);
        //设置bucket的访问权限， public-read-write权限
        client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
    }

    /**
     * 获得url链接
     * @param path 文件路径
     * @param ossClient
     * @param bucketName
     * @return
     */
    public static String getUrl(String path, OSSClient ossClient, String bucketName, String activeTime) {
        // 设置URL过期时间为10年  3600l* 1000*24*365*10
        long time = 5 * 60000;
        if (StringUtil.isNotBlank(activeTime)) {
            time = Long.parseLong(activeTime) * 60000;
        }
        Date expiration = new Date(System.currentTimeMillis() + time);
        // 生成URL
        URL url = ossClient.generatePresignedUrl(bucketName, path, expiration);
        if (url != null) {
            return url.toString();
        }
        OSSClient s = new OSSClient(url.toString(), bucketName, activeTime);
        return null;
    }

}